package com.xbongbong.paas.service.abstracts;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.data.service.RichTextService;
import com.xbongbong.paas.domain.entity.AttrTrashEntity;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasFormSubDataEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.BelongEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.AttrTrashModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasProcessDataModel;
import com.xbongbong.paas.pojo.dto.AttrTrashDTO;
import com.xbongbong.paas.pojo.dto.AttrTrashDeleteDTO;
import com.xbongbong.paas.pojo.dto.AttrTrashListDTO;
import com.xbongbong.paas.pojo.dto.AttrTrashRecoverDTO;
import com.xbongbong.paas.pojo.vo.AttrTrashDeleteVO;
import com.xbongbong.paas.pojo.vo.AttrTrashListVO;
import com.xbongbong.paas.service.PaasFormAttrTrashService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.FieldBoolQueryUtil;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.RichTextEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.dto.FieldExistDataDTO;
import com.xbongbong.pro.formdata.pojo.vo.FieldExistDataVO;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.domain.entity.competitor.CompetitorAnalysisEntity;
import com.xbongbong.saas.domain.entity.ext.WorkOrderExplainEntityExt;
import com.xbongbong.saas.domain.entity.ext.WorkOrderFormEntityExt;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.AssembleEnum;
import com.xbongbong.saas.enums.business.BomBillEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.InventoryEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.enums.business.ProductionOrderEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.QuotationEnum;
import com.xbongbong.saas.enums.business.RefundEnum;
import com.xbongbong.saas.enums.business.ReturnedPurchaseEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.enums.business.SupplierEnum;
import com.xbongbong.saas.enums.business.TransferEnum;
import com.xbongbong.saas.enums.business.WorkOrderEnum;
import com.xbongbong.saas.model.CompetitorAnalysisModel;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workflow.domain.entity.WorkflowTransferDataEntity;
import com.xbongbong.workflow.model.WorkflowTransferDataModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.existsQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author 吴峰
 * @date 2022/12/23 9:57
 */
@Slf4j
@Component
public abstract class AbstractPaasFormAttrTrashService implements PaasFormAttrTrashService {

    @Resource
    private AttrTrashModel attrTrashModel;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private RichTextService richTextService;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private WorkflowTransferDataModel workflowTransferDataModel;
    @Resource
    private PaasProcessDataModel paasProcessDataModel;
    @Resource
    private IndexTypeModel indexTypeModel;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private CompetitorAnalysisModel competitorAnalysisModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private UserModel userModel;

    @Override
    public FieldExistDataVO fieldExistData(FieldExistDataDTO fieldExistDataDTO) throws XbbException {
        FieldExistDataVO fieldExistDataVO = new FieldExistDataVO();
        try {
            Integer saasMark = fieldExistDataDTO.getSaasMark();
            String corpid = fieldExistDataDTO.getCorpid();
            IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_FORM_DATA;
            Integer businessType = fieldExistDataDTO.getBusinessType();
            Integer fieldType = fieldExistDataDTO.getFieldType();
            FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(fieldType);
            Long formId = fieldExistDataDTO.getFormId();
            if(Objects.equals(businessType, XbbRefTypeEnum.COMPETITOR_ANALYSIS.getCode())){
                // TODO: 2022/8/17 需要去查竞争对手分析数据是否存在的,需要查mysql
                boolean fieldExistData = competitorAnalysisModel.fieldExistData(corpid, fieldExistDataDTO.getAttr());
                fieldExistDataVO.setCanDelete(!fieldExistData);
                return fieldExistDataVO;
            }
            if (Objects.equals(saasMark, SaasMarkEnum.SAAS.getCode())) {
                if (Objects.equals(XbbRefTypeEnum.WORKREPORT_DAILY.getCode(), businessType)
                        || Objects.equals(XbbRefTypeEnum.WORKREPORT_MONTHLY.getCode(), businessType)
                        || Objects.equals(XbbRefTypeEnum.WORKREPORT_WEEKLY.getCode(), businessType)) {
                    businessType = XbbRefTypeEnum.WORK_REPORT.getCode();
                }
                indexTypeEnum = indexTypeModel.getIndexType(corpid, businessType, saasMark);
                //判断关联产品自定义字段是否可以删除
                String subAttr = fieldExistDataDTO.getSubAttr();
                if (StringUtil.isNotEmpty(subAttr)) {
                    boolean isProductSubAttr = isProductSubKey(fieldExistDataDTO.getAttr(),businessType,subAttr,corpid,fieldExistDataDTO.getFormId(), fieldType);
                    if (!isProductSubAttr) {
                        fieldExistDataVO.setCanDelete(false);
                        return fieldExistDataVO;
                    }
                }
            }
            if (Objects.isNull(fieldTypeEnum)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001.getCode(), MessageConstant.THIS_FIELD_TYPE_NOT_EXIST);
            }
            if (Objects.equals(BelongEnum.SAAS.getAlias(), fieldTypeEnum.getBelong())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.SYSTEM_FIELD_NOT_ALLOW_DELETE);
            } else if (Objects.equals(BelongEnum.SYSTEM.getAlias(), fieldTypeEnum.getBelong()) || Objects.equals(FieldTypeEnum.MEMO.getType(), fieldType)) {
                fieldExistDataVO.setCanDelete(true);
                return fieldExistDataVO;
            }
            //富文本字段删除特殊处理
            if(Objects.equals(fieldType, FieldTypeEnum.RICH_TEXT.getType()) && richTextService.hasData(corpid, formId)){
                fieldExistDataVO.setCanDelete(false);
                return fieldExistDataVO;
            }
            // 加下审批数据的判断
            if (!commonHelp.isOpenWorkFlow(corpid)) {
                boolean hasData = paasProcessDataModel.hasDataInApproval(corpid, saasMark, businessType, formId, fieldExistDataDTO.getAttr(), fieldExistDataDTO.getSubAttr(), fieldType, 0, 1);
                if (hasData) {
                    fieldExistDataVO.setCanDelete(false);
                    return fieldExistDataVO;
//                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FIELD_IN_PROCESS_HAVE_DATA);
                }
            } else {
                // 审批中的数据查询
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

                param.put(StringConstant.CORPID, corpid);
                param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                param.put("formId", formId);
                param.put("businessType", businessType);
                param.put("pageSize", 1);
                param.put(StringConstant.COLUMNS, " id ");
                String attrStr = "$.data.data." + fieldExistDataDTO.getAttr() ;
                if (StringUtil.isNotEmpty(fieldExistDataDTO.getSubAttr())) {
                    attrStr = attrStr + "[*]." + fieldExistDataDTO.getSubAttr();
                }
                if (Objects.equals(FieldTypeEnum.ADDRESS.getType(), fieldType)
                        || Objects.equals(FieldTypeEnum.LOCATION.getType(), fieldType)) {
                    // 地址或者定位
                    attrStr = attrStr + StringConstant.POINT + BusinessConstant.PROVINCE;
                }
                param.put("attr", attrStr);
                FieldBoolQueryUtil.fieldValueIsNull(fieldType, param);
                List<WorkflowTransferDataEntity> list = workflowTransferDataModel.hasDataInApprovalWithData(param);
                if (CollectionUtils.isNotEmpty(list)) {
                    fieldExistDataVO.setCanDelete(false);
                    return fieldExistDataVO;
                }
            }

            // 判断表单数据是否存在
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery("formId", fieldExistDataDTO.getFormId()));
            String attr = StringConstant.JSON_DATA + StringConstant.POINT + fieldExistDataDTO.getAttr();
            // 是否是子表单以及子表单内字段
            boolean isSub = false;
            if (StringUtil.isNotEmpty(fieldExistDataDTO.getSubAttr())) {
                isSub = true;
                // 子表单内字段
                indexTypeEnum = IndexTypeEnum.getSubEnum(indexTypeEnum);
                boolQueryBuilder.filter(termQuery(StringConstant.ATTR + StringConstant.POINT + StringConstant.KEY_WORD, fieldExistDataDTO.getSubAttr()));
            }
            if (ExplainUtil.isSubFormNoSelectProduct(fieldType)) {
                isSub = true;
                // 整个子表单
                indexTypeEnum = IndexTypeEnum.getSubEnum(indexTypeEnum);
                boolQueryBuilder.filter(termQuery(StringConstant.ATTR + StringConstant.POINT + StringConstant.KEY_WORD, fieldExistDataDTO.getAttr()));
                attr = StringConstant.ATTR;
            }
            boolQueryBuilder.filter(existsQuery(attr));
            boolean isAddress = Objects.equals(FieldTypeEnum.ADDRESS.getType(), fieldType) || Objects.equals(FieldTypeEnum.LOCATION.getType(), fieldType);
            boolean isFile = Objects.equals(FieldTypeEnum.IMAGE.getType(), fieldType) || Objects.equals(FieldTypeEnum.UPLOAD.getType(), fieldType);
            boolean isManaulSign = Objects.equals(FieldTypeEnum.MANUAL_SIGN.getType(), fieldType);
            if (!Objects.equals(FieldTypeEnum.NUM.getType(), fieldType) && !ExplainUtil.isSubForm(fieldType) && !isAddress && !isFile && !isManaulSign) {
                attr = attr + StringConstant.POINT + StringConstant.KEY_WORD;
            }


            // 不允许为空
            if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), fieldType)) {
                // 关联数据，判断字段存在或者非0
                boolQueryBuilder.filter(boolQuery().mustNot(termQuery(attr,0)));
                boolQueryBuilder.filter(boolQuery().mustNot(termQuery(attr,"")));
            } else if (Objects.equals(FieldTypeEnum.ADDRESS.getType(), fieldType)
                    || Objects.equals(FieldTypeEnum.LOCATION.getType(), fieldType)) {
                // 地址或者定位
                boolQueryBuilder.filter(boolQuery().mustNot(termQuery(attr + StringConstant.POINT + BusinessConstant.PROVINCE
                        + StringConstant.POINT + StringConstant.KEY_WORD,"")));
            } else if (Objects.equals(FieldTypeEnum.UPLOAD.getType(), fieldType)) {
                // 判断附件中是否含有attachIndex，如果有表示还存在未删除的文件
                boolQueryBuilder.filter(matchPhraseQuery(attr, "attachIndex"));
            } else if (Objects.equals(FieldTypeEnum.IMAGE.getType(), fieldType)) {
                boolQueryBuilder.filter(boolQuery().mustNot(termQuery(attr,"[]")));
            } else if (!Objects.equals(FieldTypeEnum.NUM.getType(), fieldType)) {
                boolQueryBuilder.filter(boolQuery().mustNot(termQuery(attr,"")));
            }
            if (!isSub && Objects.equals(SaasMarkEnum.SAAS.getCode(), saasMark)
                    && Objects.equals(XbbRefTypeEnum.CONTRACT.getCode(), fieldExistDataDTO.getBusinessType())) {
                // 合同中检索的是非红冲的合同
                boolQueryBuilder.filter(termQuery(StringConstant.JSON_DATA + StringConstant.POINT + ContractEnum.IS_RED.getAttr(), 0));
            }
            if (isSub && XbbRefTypeEnum.hasRecyleBin(saasMark, businessType)) {
                // 有回收站的子表单
                boolQueryBuilder.filter(termsQuery("del", Arrays.asList(DelEnum.NORMAL.getDel(), DelEnum.DELETE_SUBFORM.getDel())));
            } else if (XbbRefTypeEnum.hasRecyleBin(saasMark, businessType)) {
                // 有回收站的主表数据
                boolQueryBuilder.filter(termsQuery("del", Arrays.asList(DelEnum.NORMAL.getDel(), DelEnum.DELETE.getDel())));
            } else {
                boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            }
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,indexTypeEnum.getType()));
            sourceBuilder.query(boolQueryBuilder);
            SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
            searchRequest.source(sourceBuilder);
            long count = xbbElasticsearchRestTemplate.count(searchRequest, PaasFormDataEntityExt.class);
            if (count > 0) {
                fieldExistDataVO.setCanDelete(false);
                return fieldExistDataVO;
//                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FIELD_HAS_FORM_DATA);
            }
            fieldExistDataVO.setCanDelete(true);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            log.error("proFormDataService.fieldExistData 出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return fieldExistDataVO;
    }

    public boolean canDelete(String corpid, Integer businessType, Long formId, Integer fieldType, String attr, String subAttr, IndexTypeEnum indexTypeEnum) {
        // 处理列表数据, 普通子表单数据
        try {
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            String[] attrs = new String[]{subAttr, attr};
            BoolQueryBuilder boolQueryBuilder = FieldBoolQueryUtil.fieldExistDataBoolQuery(SaasMarkEnum.SAAS.getCode(), businessType, corpid, formId, fieldType, BasicConstant.TWO, attrs);
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
            sourceBuilder.query(boolQueryBuilder);
            CountRequest searchRequest = new CountRequest(indexTypeEnum.getIndex());
            searchRequest.source(sourceBuilder);
            long count = xbbElasticsearchRestTemplate.count(searchRequest);
            if (count > 0) {
                return false;
            }
            return true;
        } catch (Exception e) {
            log.error("com.xbongbong.paas.service.impl.ProFormDataServiceImpl.canDelete", e);
        }
        return false;
    }

    @Override
    public AttrTrashListVO trashList(AttrTrashListDTO attrTrashListDTO) throws XbbException {
        AttrTrashListVO attrTrashListVO = new AttrTrashListVO();
        try {
            String corpid = attrTrashListDTO.getCorpid();
            PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
            if (Objects.equals(attrTrashListDTO.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderExplainEntityExt workOrderExplainEntityExt = workOrderExplainModel.getByFormId(attrTrashListDTO.getFormId(), corpid);
                BeanUtil.copyProperties(workOrderExplainEntityExt, paasFormExplainEntity);
            } else if(Objects.equals(attrTrashListDTO.getBusinessType(), XbbRefTypeEnum.COMPETITOR_ANALYSIS.getCode())){
                attrTrashListDTO.setAppId(0L);
                attrTrashListDTO.setFormId(0L);
                attrTrashListDTO.setMenuId(0L);
                paasFormExplainEntity = paasFormExplainModel.getByBusinessTypeNoEnable(XbbRefTypeEnum.COMPETITOR_ANALYSIS.getCode(), corpid);
            } else {
                // 查看表单字段描述信息
                paasFormExplainEntity = paasFormExplainModel.getByFormId(attrTrashListDTO.getFormId(), corpid);
            }

            if (Objects.isNull(paasFormExplainEntity) || Objects.equals(paasFormExplainEntity.getDel(), DelEnum.DELETE.getDel())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            List<FieldAttrEntity> fieldAttrEntities = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            Map<String, String> attrAndNameMap = new HashMap<>();
            for (FieldAttrEntity fieldAttrEntity : fieldAttrEntities) {
                String attr = fieldAttrEntity.getAttr();
                String attrName = fieldAttrEntity.getAttrName();
                Integer fieldType = fieldAttrEntity.getFieldType();
                FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(fieldType);
                if (Objects.equals(fieldTypeEnum, FieldTypeEnum.SUB_FORM) || Objects.equals(fieldTypeEnum, FieldTypeEnum.SELECT_PRODUCT)) {
                    SubFormPoJo subForm = fieldAttrEntity.getSubForm();
                    List<? extends FieldAttrEntity> items = subForm.getItems();
                    for (FieldAttrEntity item : items) {
                        FieldTypeEnum typeEnum = FieldTypeEnum.getFieldTypeEnum(item.getFieldType());
                        String subAttr = attr + "." + item.getAttr();
                        String subAttrName = attrName +  "." + item.getAttrName() + "(" + typeEnum.getDescription() + ")";
                        attrAndNameMap.put(subAttr, subAttrName);
                    }
                } else {
                    attrName += "(" + fieldTypeEnum.getDescription() + ")";
                    attrAndNameMap.put(attr, attrName);
                }
            }


            // 处理字段回收站逻辑
            List<AttrTrashDTO> trashEntityList = new ArrayList<>();
            Map<String, Object> param = new HashMap<>();
            param.put("corpid", attrTrashListDTO.getCorpid());
            param.put("menuId", attrTrashListDTO.getMenuId());
            param.put("formId", attrTrashListDTO.getFormId());
            param.put("appId", attrTrashListDTO.getAppId());
            param.put("recover", 0);
            param.put("del", DelEnum.NORMAL.getDel());
            Integer count = attrTrashModel.getEntitysCount(param);
            param.put("start", (attrTrashListDTO.getPage() - 1) * attrTrashListDTO.getPageSize());
            param.put("pageNum", attrTrashListDTO.getPageSize());
            List<AttrTrashEntity> entitys = attrTrashModel.findEntitys(param);

            Set<String> userIds = new HashSet<>();
            entitys.forEach(item -> {
                userIds.add(item.getCreatorId());
            });
            Map<String, String> userIdNameMap = userModel.getUserIdNameMap(corpid, userIds);

            entitys.forEach(item -> {
                trashEntityList.add(new AttrTrashDTO(item.getId(), item.getAttr(), attrAndNameMap.get(item.getAttr()), userIdNameMap.get(item.getCreatorId()), item.getAddTime(), DateTimeUtil.getTodayInt(item.getAddTime() + 45 * 86400) + 86400));
            });

            PageHelper pageHelper = new PageHelper(attrTrashListDTO.getPage(), attrTrashListDTO.getPageSize());
            pageHelper.setRowsCount(count);
            attrTrashListVO.setTrashList(trashEntityList);
            attrTrashListVO.setPageHelper(pageHelper);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return attrTrashListVO;
    }

    @Override
    public BaseVO trashRecover(AttrTrashRecoverDTO attrTrashRecoverDTO) throws XbbException {
        try {
            String corpid = attrTrashRecoverDTO.getCorpid();
            AttrTrashEntity trashEntity = attrTrashModel.getByKey(attrTrashRecoverDTO.getId(), corpid);
            if (Objects.isNull(trashEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            trashEntity.setRecover(1);
            attrTrashModel.update(trashEntity);

            Integer businessType = trashEntity.getBusinessType();

            String formName;
            StringBuffer attrName = new StringBuffer();

            PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
            if (Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderExplainEntityExt workOrderExplainEntityExt = workOrderExplainModel.getByFormId(trashEntity.getFormId(), corpid);
                BeanUtil.copyProperties(workOrderExplainEntityExt, paasFormExplainEntity);
                if (Objects.isNull(paasFormExplainEntity)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
                }
                WorkOrderFormEntityExt workOrderFormEntityExt = workOrderFormModel.getByKey(workOrderExplainEntityExt.getFormId(), corpid);
                formName = workOrderFormEntityExt.getName();
            } else if(Objects.equals(businessType, XbbRefTypeEnum.COMPETITOR_ANALYSIS.getCode())){
                paasFormExplainEntity = paasFormExplainModel.getByBusinessTypeNoEnable(XbbRefTypeEnum.COMPETITOR_ANALYSIS.getCode(), corpid);
                if (Objects.isNull(paasFormExplainEntity)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
                }
                PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(paasFormExplainEntity.getFormId(), corpid);
                formName = paasFormEntityExt.getName();
            } else {
                paasFormExplainEntity = paasFormExplainModel.getByFormId(trashEntity.getFormId(), corpid);
                if (Objects.isNull(paasFormExplainEntity)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
                }
                PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(paasFormExplainEntity.getFormId(), corpid);
                formName = paasFormEntityExt.getName();
            }

            String attr = trashEntity.getAttr();
            String[] attrs = attr.split("\\.");
            List<FieldAttrEntity> fieldAttrEntities = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            // 是否是子表单字段
            boolean isSub = attrs.length == 2;
            for (FieldAttrEntity fieldAttrEntity : fieldAttrEntities) {
                String parentAttr = fieldAttrEntity.getAttr();
                if (isSub) {
                    if (Objects.equals(parentAttr, attrs[0])) {
                        SubFormPoJo subForm = fieldAttrEntity.getSubForm();
                        List<? extends FieldAttrEntity> items = subForm.getItems();
                        items.forEach(item -> {
                            if (Objects.equals(attrs[1], item.getAttr())) {
                                item.setIsOpen(1);
                                attrName.append(fieldAttrEntity.getAttrName()).append(StringConstant.POINT).append(item.getAttrName());
                            }
                        });
                    }
                } else {
                    if (Objects.equals(parentAttr, attrs[0])) {
                        fieldAttrEntity.setIsOpen(1);
                        attrName.append(fieldAttrEntity.getAttrName());
                    }
                }
            }

            paasFormExplainEntity.setExplains(JSON.toJSONString(fieldAttrEntities));

            if (Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderExplainEntity workOrderExplainEntity = new WorkOrderExplainEntity();
                BeanUtil.copyProperties(paasFormExplainEntity, workOrderExplainEntity);
                workOrderExplainModel.update(workOrderExplainEntity);
            } else {
                paasFormExplainModel.update(paasFormExplainEntity);
            }

            // 恢复日志
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_RECOVER_ATTR), attrTrashRecoverDTO.getLoginUserName(), formName, attrName.toString());
            mongoLogHelp.buildLog(corpid, attrTrashRecoverDTO.getUserId(), attrTrashRecoverDTO.getLoginUserName(), OperateModuleTypeEnum.PAAS_FORM, OperateTypeEnum.ATTR_RECOVER, trashEntity.getId().toString(), formName + StringConstant.UNDER_LINE + attrName.toString(), memo, attrTrashRecoverDTO.getHttpHeader());


        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return new BaseVO();
    }



    @Override
    public AttrTrashDeleteVO trashDelete(AttrTrashDeleteDTO attrTrashDeleteDTO) throws XbbException {
        AttrTrashDeleteVO attrTrashDeleteVO = new AttrTrashDeleteVO();
        try {
            String corpid = attrTrashDeleteDTO.getCorpid();
            AttrTrashEntity trashEntity = attrTrashModel.getByKey(attrTrashDeleteDTO.getId(), corpid);
            if (Objects.isNull(trashEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            Long formId = trashEntity.getFormId();
            Integer saasMark = trashEntity.getSaasMark();
            PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
            Integer businessType = trashEntity.getBusinessType();
            if (Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderExplainEntityExt workOrderExplainEntityExt = workOrderExplainModel.getByFormId(trashEntity.getFormId(), corpid);
                BeanUtil.copyProperties(workOrderExplainEntityExt, paasFormExplainEntity);
            } else if(Objects.equals(businessType, XbbRefTypeEnum.COMPETITOR_ANALYSIS.getCode())) {
                // 竞争对手分析需要特殊处理
                return trashDelete4CompetitorAnalysis(attrTrashDeleteDTO,trashEntity);
            } else {
                paasFormExplainEntity = paasFormExplainModel.getByFormId(trashEntity.getFormId(), corpid);
            }
            List<FieldAttrEntity> fieldAttrEntities = JSON.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            String attr = trashEntity.getAttr();
            String[] attrs = attr.split("\\.");
            // 是否是子表单字段
            boolean isSub = attrs.length == 2;
            // 字段类型
            Integer fieldType = null;
            for (FieldAttrEntity fieldAttrEntity : fieldAttrEntities) {
                String parentAttr = fieldAttrEntity.getAttr();
                if (isSub) {
                    if (Objects.equals(parentAttr, attrs[0])) {
                        SubFormPoJo subForm = fieldAttrEntity.getSubForm();
                        List<? extends FieldAttrEntity> items = subForm.getItems();
                        for (FieldAttrEntity item : items) {
                            if (Objects.equals(attrs[1], item.getAttr())) {
                                fieldType = item.getFieldType();
                            }
                        }
                    }
                } else {
                    if (Objects.equals(parentAttr, attrs[0])) {
                        fieldType = fieldAttrEntity.getFieldType();
                    }
                }
            }

            //富文本字段单独处理
            if(Objects.equals(fieldType, FieldTypeEnum.RICH_TEXT.getType())){
                attrTrashDeleteVO.setCanDel(richTextService.trashDelete(corpid, formId, saasMark, businessType));
                attrTrashModel.deleteByKey(trashEntity.getId(), corpid);
                return attrTrashDeleteVO;
            }

            // 判断字段是否有500条数据（审批中+列表）
            int approvalCount;
            // 审批中的数据查询
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("formId", trashEntity.getFormId());
            param.put("businessType", businessType);
            param.put("pageSize", 501);
            param.put(StringConstant.COLUMNS, " id ");
            if (commonHelp.isOpenWorkFlow(corpid)) {
                String attrStr;
                if (isSub) {
                    attrStr = "$.data.data." + attrs[0] + "[*]." + attrs[1];
                } else {
                    attrStr = "$.data.data." + attrs[0];
                }
                if (Objects.equals(FieldTypeEnum.ADDRESS.getType(), fieldType)
                        || Objects.equals(FieldTypeEnum.LOCATION.getType(), fieldType)) {
                    // 地址或者定位
                    attrStr = attrStr + StringConstant.POINT + BusinessConstant.PROVINCE;
                }
                param.put("attr", attrStr);
                FieldBoolQueryUtil.fieldValueIsNull(fieldType, param);
                List<WorkflowTransferDataEntity> list = workflowTransferDataModel.hasDataInApprovalWithData(param);
                approvalCount = list.size();
            } else {
                String attrStr;
                if (isSub) {
                    attrStr = "$." + attrs[0] + "[*]." + attrs[1];
                } else {
                    attrStr = "$." + attrs[0];
                }
                if (Objects.equals(FieldTypeEnum.ADDRESS.getType(), fieldType)
                        || Objects.equals(FieldTypeEnum.LOCATION.getType(), fieldType)) {
                    // 地址或者定位
                    attrStr = attrStr + StringConstant.POINT + BusinessConstant.PROVINCE;
                }
                param.put("attr", attrStr);
                FieldBoolQueryUtil.fieldValueIsNull(fieldType, param);
                // 审批中的数量
                List<PaasProcessDataEntity> list = paasProcessDataModel.hasDataInApprovalWithData(param);
                approvalCount = list.size();
            }


            // 列表的数据查询
            Long productNum = 0L;
            if (Objects.equals(SaasMarkEnum.SAAS.getCode(), trashEntity.getSaasMark())) {
                if (Objects.equals(XbbRefTypeEnum.WORKREPORT_DAILY.getCode(), businessType) || Objects.equals(XbbRefTypeEnum.WORKREPORT_WEEKLY.getCode(), businessType) || Objects.equals(XbbRefTypeEnum.WORKREPORT_MONTHLY.getCode(), businessType)) {
                    businessType = XbbRefTypeEnum.WORK_REPORT.getCode();
                }
                if (isSub) {
                    productNum = countProductNum(attrs[0], attrs[1], businessType, corpid, trashEntity.getFormId(), fieldType);
                }

            }

            // 列表数据的处理
            Long listCount = 0L;
            if (Objects.equals(productNum, 0L)) {
                // 普通子表单的处理
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termQuery("formId", trashEntity.getFormId()));
                IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(corpid, businessType, trashEntity.getSaasMark());

                String esAttrStr;
                if (isSub) {
                    indexTypeEnum = IndexTypeEnum.getSubEnum(indexTypeEnum);
                    boolQueryBuilder.filter(termQuery(StringConstant.ATTR + StringConstant.POINT + StringConstant.KEY_WORD, attrs[0]));
                    esAttrStr = StringConstant.JSON_DATA + StringConstant.POINT + attrs[1];
                } else {
                    esAttrStr = StringConstant.JSON_DATA + StringConstant.POINT + attrs[0];
                }
                boolQueryBuilder.filter(existsQuery(esAttrStr));

                boolean isAddress = Objects.equals(FieldTypeEnum.ADDRESS.getType(), fieldType) || Objects.equals(FieldTypeEnum.LOCATION.getType(), fieldType);
                boolean isFile = Objects.equals(FieldTypeEnum.IMAGE.getType(), fieldType) || Objects.equals(FieldTypeEnum.UPLOAD.getType(), fieldType) || Objects.equals(FieldTypeEnum.MANUAL_SIGN.getType(), fieldType);
                if (!Objects.equals(FieldTypeEnum.NUM.getType(), fieldType) && !ExplainUtil.isSubForm(fieldType) && !isAddress && !isFile) {
                    esAttrStr += StringConstant.POINT + StringConstant.KEY_WORD;
                }
                // 参数拼装
                FieldBoolQueryUtil.fieldValueIsNull(fieldType, esAttrStr, boolQueryBuilder);

                if (!isSub && Objects.equals(SaasMarkEnum.SAAS.getCode(), trashEntity.getSaasMark()) && Objects.equals(XbbRefTypeEnum.CONTRACT.getCode(), businessType)) {
                    // 合同中检索的是非红冲的合同
                    boolQueryBuilder.filter(termQuery(StringConstant.JSON_DATA + StringConstant.POINT + ContractEnum.IS_RED.getAttr(), 0));
                }
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
                sourceBuilder.query(boolQueryBuilder);
                SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
                searchRequest.source(sourceBuilder);
                CountRequest countRequest = new CountRequest(searchRequest.indices()[0]);
                countRequest.query(searchRequest.source().query());
                listCount = xbbElasticsearchRestTemplate.count(countRequest);
            }

            // 大于500条不能直接删除
            boolean canDel = true;
            if (approvalCount + productNum + listCount > 500) {
                canDel = false;
            } else {
                // 异步删除逻辑
                Runnable runnable = () -> {
                    try {
                        trashDeleteAsync(Collections.singletonList(trashEntity), attrTrashDeleteDTO.getLoginUser());
                    } catch (XbbException e) {
                        log.error("com.xbongbong.paas.service.impl.PaasFormAttrTrashServiceImpl.trashDelete ", e);
                    }
                };
                threadPoolBeanConfig.attrTrashDelete().execute(runnable);
            }

            attrTrashDeleteVO.setCanDel(canDel);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return attrTrashDeleteVO;
    }

    @Override
    public void trashDeleteJobs(List<AttrTrashEntity> attrTrashEntityList, UserVO loginUser) throws XbbException {
        Runnable runnable = () -> {
            try {
                trashDeleteAsync(attrTrashEntityList, loginUser);
            } catch (XbbException e) {
                log.error("com.xbongbong.paas.service.impl.PaasFormAttrTrashServiceImpl.trashDelete ", e);
            }
        };
        threadPoolBeanConfig.attrTrashDelete().execute(runnable);
    }

    private void trashDeleteAsync(List<AttrTrashEntity> attrTrashEntityList, UserVO loginUser) throws XbbException {
        if (Objects.isNull(attrTrashEntityList)) {
            return;
        }
        boolean workflow = commonHelp.isOpenWorkFlow(attrTrashEntityList.get(0).getCorpid());
        PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
        for (AttrTrashEntity trashEntity : attrTrashEntityList) {
            String corpid = trashEntity.getCorpid();
            Long formId = trashEntity.getFormId();

            //富文本单独处理
            if (Objects.equals(trashEntity.getAttr(), RichTextEnum.RICH_TEXT.getAttr())){
                richTextService.trashDelete(trashEntity);
                continue;
            }
            String formName;
            StringBuffer attrName = new StringBuffer();
            Integer businessType = trashEntity.getBusinessType();
            Integer saasMark = trashEntity.getSaasMark();
            if (Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderExplainEntity workOrderExplainEntity = workOrderExplainModel.getByFormId(formId, corpid);
                if (Objects.isNull(workOrderExplainEntity)) {
                    log.error("com.xbongbong.paas.service.impl.PaasFormAttrTrashServiceImpl.trashDeleteJobs failed,because explain don't exist， corpid=" + corpid + ", attrTrashId=" + trashEntity.getId());
                    continue;
                }
                BeanUtil.copyProperties(workOrderExplainEntity, paasFormExplainEntity);
                WorkOrderFormEntityExt workOrderFormEntityExt = workOrderFormModel.getByKey(workOrderExplainEntity.getFormId(), workOrderExplainEntity.getCorpid());
                formName = workOrderFormEntityExt.getName();

            } else if(Objects.equals(businessType, XbbRefTypeEnum.COMPETITOR_ANALYSIS.getCode())){
                deleteCompeterAnalysis(trashEntity,loginUser);
                continue;
            } else {
                paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
                if (Objects.isNull(paasFormExplainEntity)) {
                    log.error("com.xbongbong.paas.service.impl.PaasFormAttrTrashServiceImpl.trashDeleteJobs failed,because explain don't exist， corpid=" + corpid + ", attrTrashId=" + trashEntity.getId());
                    continue;
                }
                PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(paasFormExplainEntity.getFormId(), corpid);
                formName = paasFormEntityExt.getName();
            }

            List<FieldAttrEntity> fieldAttrEntities = JSON.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);

            String attr = trashEntity.getAttr();
            String[] attrs = attr.split("\\.");
            // 是否是子表单字段
            boolean isSub = attrs.length == 2;
            // 字段类型
            Integer fieldType = null;
            Iterator<FieldAttrEntity> iterator = fieldAttrEntities.iterator();
            while (iterator.hasNext()) {
                FieldAttrEntity fieldAttrEntity = iterator.next();
                String parentAttr = fieldAttrEntity.getAttr();
                if (isSub) {
                    if (Objects.equals(parentAttr, attrs[0])) {
                        SubFormPoJo subForm = fieldAttrEntity.getSubForm();
                        List<? extends FieldAttrEntity> items = subForm.getItems();
                        Iterator<? extends FieldAttrEntity> iter = items.iterator();
                        while (iter.hasNext()) {
                            FieldAttrEntity item = iter.next();
                            if (Objects.equals(attrs[1], item.getAttr()) && Objects.equals(item.getIsOpen(), 2)) {
                                fieldType = item.getFieldType();
                                attrName.append(fieldAttrEntity.getAttrName()).append(StringConstant.POINT).append(item.getAttrName());
                                iter.remove();
                            }
                        }
                    }
                } else {
                    if (Objects.equals(parentAttr, attrs[0]) && Objects.equals(fieldAttrEntity.getIsOpen(), 2)) {
                        fieldType = fieldAttrEntity.getFieldType();
                        attrName.append(fieldAttrEntity.getAttrName());
                        iterator.remove();
                    }
                }
            }
            if (Objects.isNull(fieldType)) {
                continue;
            }
            // 删除记录
            attrTrashModel.deleteByKey(trashEntity.getId(), corpid);

            // 更新解释
            paasFormExplainEntity.setExplains(JSON.toJSONString(fieldAttrEntities, SerializerFeature.DisableCircularReferenceDetect));
            if (Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderExplainEntity workOrderExplainEntity = new WorkOrderExplainEntity();
                BeanUtil.copyProperties(paasFormExplainEntity, workOrderExplainEntity);
                workOrderExplainModel.update(workOrderExplainEntity);
            } else {
                paasFormExplainModel.update(paasFormExplainEntity);
            }
            if (workflow) {
                // 处理工作流上下文
                executeWorkflowData(fieldType, attrs, isSub, corpid, formId, businessType);
            } else {
                // 处理流程数据
                executeProcessData(fieldType, attrs, isSub, corpid, formId, businessType);
            }


            // 处理关联产品内的自定义字段
            boolean isProduct = false;
            if (Objects.equals(SaasMarkEnum.SAAS.getCode(), trashEntity.getSaasMark())) {
                if (Objects.equals(XbbRefTypeEnum.WORKREPORT_DAILY.getCode(), businessType) || Objects.equals(XbbRefTypeEnum.WORKREPORT_WEEKLY.getCode(), businessType) || Objects.equals(XbbRefTypeEnum.WORKREPORT_MONTHLY.getCode(), businessType)) {
                    businessType = XbbRefTypeEnum.WORK_REPORT.getCode();
                }
                if (isSub) {
                    isProduct = checkIsProduct(attrs[0], businessType);
                }
            }

            if (isProduct) {
                // 处理在关联产品特殊子表单中的数据
                deleteProductSubData(attrs[0], attrs[1], businessType, corpid, formId, fieldType);
            } else {
                // 处理列表数据, 普通子表单数据
                BoolQueryBuilder boolQueryBuilder = FieldBoolQueryUtil.fieldExistDataBoolQuery(saasMark, businessType, corpid, formId, fieldType, BasicConstant.ONE, attrs);
                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(corpid, businessType, saasMark);

                if (isSub) {
                    indexTypeEnum = IndexTypeEnum.getSubEnum(indexTypeEnum);
                }
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, indexTypeEnum.getType()));
                boolean flag = true;
                while (flag) {
                    sourceBuilder.query(boolQueryBuilder);
                    sourceBuilder.sort("id");
                    sourceBuilder.size(PaasConstant.ES_MAX_PAGE_SIZE);
                    SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
                    searchRequest.source(sourceBuilder);
                    if (isSub) {
                        // 子表单字段删除
                        XbbAggregatedPage<PaasFormSubDataEntity> paasFormSubDataEntityXbbAggregatedPage = xbbElasticsearchRestTemplate.queryForPages(searchRequest, PaasFormSubDataEntity.class);
                        List<PaasFormSubDataEntity> paasFormSubDataEntities = paasFormSubDataEntityXbbAggregatedPage.getContent();
                        if (Objects.nonNull(paasFormSubDataEntities) && paasFormSubDataEntities.size() != 0) {
                            boolQueryBuilder.filter(rangeQuery("id").gt(paasFormSubDataEntities.get(paasFormSubDataEntities.size() - 1).getId()));

                            List<UpdateDataEntity> updateList = new ArrayList<>();
                            for (PaasFormSubDataEntity paasFormSubDataEntity : paasFormSubDataEntities) {
                                JSONObject data = paasFormSubDataEntity.getData();
                                JSONObject updateJson = new JSONObject();
                                Iterator<Map.Entry<String, Object>> iter = data.entrySet().iterator();
                                while (iter.hasNext()) {
                                    Map.Entry<String, Object> obj = iter.next();
                                    String key = obj.getKey();
                                    if (Objects.equals(obj.getKey(), attrs[1])) {
                                        if (obj.getValue() instanceof JSONArray) {
                                            updateJson.put(key, new JSONArray());
                                        } else {
                                            updateJson.put(key, null);
                                        }
                                    }
                                }

                                UpdateDataEntity updateData = ExplainUtil.getUpdateData(paasFormSubDataEntity.getId(), updateJson, corpid);
                                // 子表单更新需要设置parentId
                                updateData.setParentId(paasFormSubDataEntity.getDataId());
                                updateList.add(updateData);
                            }


                            updateSubData(updateList, corpid, indexTypeEnum);

                        } else {
                            flag = false;
                        }
                    } else {
                        XbbAggregatedPage<PaasFormDataEntity> paasFormDataEntityXbbAggregatedPage = xbbElasticsearchRestTemplate.queryForPages(searchRequest, PaasFormDataEntity.class);
                        List<PaasFormDataEntity> paasFormDataEntities = paasFormDataEntityXbbAggregatedPage.getContent();
                        if (paasFormDataEntities.size() != 0) {

                            boolQueryBuilder.filter(rangeQuery("id").gt(paasFormDataEntities.get(paasFormDataEntities.size() - 1).getId()));

                            List<UpdateDataEntity> updateList = new ArrayList<>();

                            for (PaasFormDataEntity paasFormDataEntity : paasFormDataEntities) {
                                JSONObject data = paasFormDataEntity.getData();
                                Iterator<Map.Entry<String, Object>> iter = data.entrySet().iterator();
                                JSONObject updateJson = new JSONObject();
                                while (iter.hasNext()) {
                                    Map.Entry<String, Object> obj = iter.next();
                                    String key = obj.getKey();
                                    if (Objects.equals(obj.getKey(), attrs[0])) {
                                        if (obj.getValue() instanceof JSONArray) {
                                            updateJson.put(key, new JSONArray());
                                        } else {
                                            updateJson.put(key, null);
                                        }
                                    }
                                }

                                // TODO: 2021/3/12
                                UpdateDataEntity updateData = ExplainUtil.getUpdateData(paasFormDataEntity.getId(), updateJson, corpid);
                                updateList.add(updateData);
                            }

                            updateBatch(trashEntity, corpid, updateList);
                        } else {
                            flag = false;
                        }
                    }

                }
            }


            String memo;
            if (Objects.nonNull(loginUser)) {
                // 手动
                memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_COMPLETELY_DELETE_ATTR), loginUser.getName(), formName, attrName.toString());
                mongoLogHelp.buildLog(corpid, loginUser.getUserId(), loginUser.getName(), OperateModuleTypeEnum.PAAS_FORM, OperateTypeEnum.ATTR_DELETE, trashEntity.getId().toString(), formName + StringConstant.UNDER_LINE + attrName.toString(), memo, null);

            } else {
                // 系统
                memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_SYS_COMPLETELY_DELETE_ATTR), formName, attrName.toString());
                mongoLogHelp.buildLog(corpid, PaasConstant.SYS_USER_ID, I18nMessageUtil.getMessage(PaasConstant.SYS_OPERATING), OperateModuleTypeEnum.PAAS_FORM, OperateTypeEnum.ATTR_DELETE, trashEntity.getId().toString(), formName + StringConstant.UNDER_LINE + attrName.toString(), memo, null);
            }

        }

    }



    /**
     * Description: 判断是否是关联产品的内的
     * @param attr
     * @param businessType
     * @return boolean
     * @throws
     * @author 魏荣杰
     * @date 2021/3/16 14:32
     * @since
     */
    protected boolean checkIsProduct(String attr, Integer businessType) {
        boolean isProduct = false;
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        switch (xbbRefTypeEnum){
            case CONTRACT:
                if (Objects.equals(attr, ContractEnum.PRODUCT.getAttr())) {
                    isProduct = true;
                }
                break;
            case SALES_OPPORTUNITY:
                if (Objects.equals(attr, SalesOpportunityEnum.PRODUCTS.getAttr())) {
                    isProduct = true;
                }
                break;
            case REFUND:
                if (Objects.equals(attr, RefundEnum.PRODUCTS.getAttr())) {
                    isProduct = true;
                }
                break;
            case QUOTATION:
                if (Objects.equals(attr, QuotationEnum.PRODUCT.getAttr())) {
                    isProduct = true;
                }
                break;
            case SUPPLIER:
                if (Objects.equals(attr, SupplierEnum.PRODUCT_LIST.getAttr())) {
                    isProduct = true;
                }
                break;
            case PURCHASE:
                if (Objects.equals(attr, PurchaseEnum.PRODUCT.getAttr())) {
                    isProduct = true;
                }
                break;
            case RETURNED_PURCHASE:
                if (Objects.equals(attr, ReturnedPurchaseEnum.PRODUCTS.getAttr())) {
                    isProduct = true;
                }
                break;
            case BOM_BILL:
                if (Objects.equals(attr, BomBillEnum.PRODUCT.getAttr())) {
                    isProduct = true;
                }else if (Objects.equals(attr, BomBillEnum.MATERIEL.getAttr())){
                    isProduct = true;
                }
                break;
            case PRODUCTION_ORDER:
                if (Objects.equals(attr, ProductionOrderEnum.PRODUCT.getAttr())) {
                    isProduct = true;
                } else if (Objects.equals(attr, ProductionOrderEnum.MATERIEL.getAttr())) {
                    isProduct = true;
                }
                break;
            case ASSEMBLE:
                if (Objects.equals(attr, AssembleEnum.IN_PRODUCTS.getAttr())) {
                    isProduct = true;
                }else if (Objects.equals(attr, AssembleEnum.OUT_PRODUCTS.getAttr())) {
                    isProduct = true;
                }
                break;
            case INSTOCK:
            case PURCHASE_INSTOCK:
            case REFUND_INSTOCK:
            case OTHER_INSTOCK:
            case PRODUCTION_INSTOCK:
            case RETURNED_MATERIEL_INSTOCK:
                if (Objects.equals(attr, InstockEnum.PRODUCT.getAttr())) {
                    isProduct = true;
                }
                break;
            case OUTSTOCK:
            case CONTRACT_OUTSTOCK:
            case RETURNED_PURCHASE_OUTSTOCK:
            case OTHER_OUTSTOCK:
            case PRODUCTION_MATERIEL_OUTSTOCK:
            case WORK_ORDER_OUTSTOCK:
                if (Objects.equals(attr, OutstockEnum.PRODUCT.getAttr())) {
                    isProduct = true;
                }
                break;
            case INVENTORY:
                if (Objects.equals(attr, InventoryEnum.PRODUCT.getAttr())) {
                    isProduct = true;
                }
                break;
            case TRANSFER:
                if (Objects.equals(attr, TransferEnum.PRODUCTS.getAttr())) {
                    isProduct = true;
                }
                break;
            case WORK_ORDER:
                if (Objects.equals(attr, WorkOrderEnum.SPARE_PARTS.getAttr())) {
                    isProduct = true;
                }
                break;
            default:
        }
        return isProduct;
    }



    private void deleteCompeterAnalysis(AttrTrashEntity trashEntity,UserVO loginUser) throws XbbException{
        String corpid = trashEntity.getCorpid();
        Long formId = trashEntity.getFormId();
        String attr = trashEntity.getAttr();
        String formName;
        StringBuffer attrName = new StringBuffer();
        Integer businessType = trashEntity.getBusinessType();
        Integer saasMark = trashEntity.getSaasMark();
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessTypeNoEnable(XbbRefTypeEnum.COMPETITOR_ANALYSIS.getCode(), corpid);
        if (Objects.isNull(paasFormExplainEntity)) {
            log.error("com.xbongbong.paas.service.impl.PaasFormAttrTrashServiceImpl.trashDeleteJobs failed,because explain don't exist， corpid=" + corpid + ", attrTrashId=" + trashEntity.getId());
            return;
        }
        formName = XbbRefTypeEnum.COMPETITOR_ANALYSIS.getName();
        // 更新解释
        List<FieldAttrEntity> fieldAttrEntities = JSON.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);

        Iterator<FieldAttrEntity> iterator = fieldAttrEntities.iterator();
        while (iterator.hasNext()) {
            FieldAttrEntity fieldAttrEntity = iterator.next();
            String parentAttr = fieldAttrEntity.getAttr();
            if (Objects.equals(parentAttr, attr) && Objects.equals(fieldAttrEntity.getIsOpen(), 2)) {
                attrName.append(fieldAttrEntity.getAttrName());
                iterator.remove();
            }
        }
        paasFormExplainEntity.setExplains(JSON.toJSONString(fieldAttrEntities, SerializerFeature.DisableCircularReferenceDetect));
        paasFormExplainModel.update(paasFormExplainEntity);
        // 竞争对手字段 不太一样 需要特殊处理
        List<CompetitorAnalysisEntity> competitorAnalysisEntityList = competitorAnalysisModel.listFieldExistData(corpid,attr);
        List<UpdateDataEntity> updateList = new ArrayList<>();
        competitorAnalysisEntityList.forEach(item->{
            JSONObject data = item.getData();
            data.put(attr,null);
            JSONObject updateJson = new JSONObject();
            updateJson.put(attr, null);
            UpdateDataEntity updateData = ExplainUtil.getUpdateData(item.getId(), updateJson, corpid);
            updateList.add(updateData);
        });
        competitorAnalysisModel.updateBatch(updateList,corpid);
        // 删除记录
        attrTrashModel.deleteByKey(trashEntity.getId(), corpid);
        String memo;
        if (Objects.nonNull(loginUser)) {
            // 手动
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_COMPLETELY_DELETE_ATTR), loginUser.getName(), formName, attrName.toString());
            mongoLogHelp.buildLog(corpid, loginUser.getUserId(), loginUser.getName(), OperateModuleTypeEnum.PAAS_FORM, OperateTypeEnum.ATTR_DELETE, trashEntity.getId().toString(), formName + StringConstant.UNDER_LINE + attrName.toString(), memo, null);
        } else {
            // 系统
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_SYS_COMPLETELY_DELETE_ATTR), formName, attrName.toString());
            mongoLogHelp.buildLog(corpid, PaasConstant.SYS_USER_ID, I18nMessageUtil.getMessage(PaasConstant.SYS_OPERATING), OperateModuleTypeEnum.PAAS_FORM, OperateTypeEnum.ATTR_DELETE, trashEntity.getId().toString(), formName + StringConstant.UNDER_LINE + attrName.toString(), memo, null);
        }
    }



    private void executeWorkflowData(Integer fieldType, String[] attrs, boolean isSub, String corpid, Long formId, Integer businessType) {
        // 审批的数据处理
        String attrStr;
        if (isSub) {
            attrStr = "$.data.data." + attrs[0] + "[*]." + attrs[1];
        } else {
            attrStr = "$.data.data." + attrs[0];
        }
        if (Objects.equals(FieldTypeEnum.ADDRESS.getType(), fieldType)
                || Objects.equals(FieldTypeEnum.LOCATION.getType(), fieldType)) {
            // 地址或者定位
            attrStr = attrStr + StringConstant.POINT + BusinessConstant.PROVINCE;
        }
        Map<String, Object> param = FieldBoolQueryUtil.getFieldData(fieldType, attrStr, corpid, formId, businessType);

        while (true) {
            List<WorkflowTransferDataEntity> workflowTransferDataEntities = workflowTransferDataModel.hasDataInApprovalWithData(param);
            if (workflowTransferDataEntities.isEmpty()) {
                break;
            } else {
                param.put("idGte", workflowTransferDataEntities.get(workflowTransferDataEntities.size() - 1).getId());

                Iterator<WorkflowTransferDataEntity> iter = workflowTransferDataEntities.iterator();
                while (iter.hasNext()) {
                    WorkflowTransferDataEntity workflowTransferDataEntity = iter.next();
                    JSONObject workflowTransferPOJO = workflowTransferDataEntity.getData();

                    JSONObject data = workflowTransferPOJO.getJSONObject("data").getJSONObject("data");
                    Iterator<Map.Entry<String, Object>> it = data.entrySet().iterator();
                    while (it.hasNext()) {
                        Map.Entry<String, Object> obj = it.next();
                        if (isSub) {
                            if (Objects.equals(obj.getKey(), attrs[0])) {
                                JSONArray jsonArray = JSON.parseArray(obj.getValue().toString());
                                Iterator<Object> subIterator = jsonArray.iterator();
                                while (subIterator.hasNext()) {
                                    JSONObject subObj = (JSONObject) subIterator.next();
                                    Iterator<Map.Entry<String, Object>> entryIterator = subObj.entrySet().iterator();
                                    while (entryIterator.hasNext()) {
                                        Map.Entry<String, Object> stringObjectEntry = entryIterator.next();
                                        if (Objects.equals(stringObjectEntry.getKey(), attrs[1])) {
                                            entryIterator.remove();
                                        }
                                    }

                                }
                                data.put(obj.getKey(), jsonArray);
                            }
                        } else {
                            if (Objects.equals(obj.getKey(), attrs[0])) {
                                it.remove();
                            }
                        }
                    }
                    workflowTransferDataEntity.setData(workflowTransferPOJO);
                }
                // 更新审批数据
                workflowTransferDataModel.updateDataBatch(workflowTransferDataEntities, corpid);

            }
        }
    }


    private void executeProcessData(Integer fieldType, String[] attrs, boolean isSub, String corpid, Long formId, Integer businessType) {
        // 审批的数据处理
        String attrStr;
        if (isSub) {
            attrStr = "$." + attrs[0] + "[*]." + attrs[1];
        } else {
            attrStr = "$." + attrs[0];
        }
        if (Objects.equals(FieldTypeEnum.ADDRESS.getType(), fieldType)
                || Objects.equals(FieldTypeEnum.LOCATION.getType(), fieldType)) {
            // 地址或者定位
            attrStr = attrStr + StringConstant.POINT + BusinessConstant.PROVINCE;
        }
        Map<String, Object> param = FieldBoolQueryUtil.getFieldData(fieldType, attrStr, corpid, formId, businessType);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());


        boolean flag = true;
        while (flag) {
            List<PaasProcessDataEntity> paasProcessDataEntities = paasProcessDataModel.hasDataInApprovalWithData(param);
            if (paasProcessDataEntities.isEmpty()) {
                flag = false;
            } else {
                param.put("idGte", paasProcessDataEntities.get(paasProcessDataEntities.size() - 1).getId());

                Iterator<PaasProcessDataEntity> iter = paasProcessDataEntities.iterator();
                while (iter.hasNext()) {
                    PaasProcessDataEntity paasProcessDataEntity = iter.next();
                    String data = paasProcessDataEntity.getData();
                    JSONObject jsonObject = JSON.parseObject(data);
                    Iterator<Map.Entry<String, Object>> it = jsonObject.entrySet().iterator();
                    while (it.hasNext()) {
                        Map.Entry<String, Object> obj = it.next();
                        if (isSub) {
                            if (Objects.equals(obj.getKey(), attrs[0])) {
                                JSONArray jsonArray = JSON.parseArray(obj.getValue().toString());
                                Iterator<Object> subIterator = jsonArray.iterator();
                                while (subIterator.hasNext()) {
                                    JSONObject subObj = (JSONObject) subIterator.next();
                                    Iterator<Map.Entry<String, Object>> entryIterator = subObj.entrySet().iterator();
                                    while (entryIterator.hasNext()) {
                                        Map.Entry<String, Object> stringObjectEntry = entryIterator.next();
                                        if (Objects.equals(stringObjectEntry.getKey(), attrs[1])) {
                                            entryIterator.remove();
                                        }
                                    }

                                }
                                jsonObject.put(obj.getKey(), jsonArray);
                            }
                        } else {
                            if (Objects.equals(obj.getKey(), attrs[0])) {
                                it.remove();
                            }
                        }
                    }
                    paasProcessDataEntity.setData(JSON.toJSONString(jsonObject));
                }
                // 更新审批数据
                paasProcessDataModel.updateBatch(paasProcessDataEntities, corpid);

            }
        }
    }

    /**
     *  竞争对手分析在字段回收站删除字段
     * date: 2022/9/6 6:31 下午
     * @author yingjf
     * @param attrTrashDeleteDTO:
     * @param trashEntity:
     */
    private AttrTrashDeleteVO trashDelete4CompetitorAnalysis(AttrTrashDeleteDTO attrTrashDeleteDTO,AttrTrashEntity trashEntity)throws XbbException{
        AttrTrashDeleteVO attrTrashDeleteVO = new AttrTrashDeleteVO();
        String corpid = attrTrashDeleteDTO.getCorpid();
        //PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
        Integer businessType = trashEntity.getBusinessType();
        String attr = trashEntity.getAttr();

        //paasFormExplainEntity = paasFormExplainModel.getByBusinessTypeNoEnable(XbbRefTypeEnum.COMPETITOR_ANALYSIS.getCode(),corpid);
        Long listCount = 0L;
        listCount = competitorAnalysisModel.countFieldExistData(corpid, attr);
        // 大于500条不能直接删除
        boolean canDel = true;
        if (listCount > 500) {
            canDel = false;
        } else {
            // 异步删除逻辑
            Runnable runnable = () -> {
                try {
                    trashDeleteJobs(Collections.singletonList(trashEntity), attrTrashDeleteDTO.getLoginUser());
                } catch (XbbException e) {
                    log.error("com.xbongbong.paas.service.impl.PaasFormAttrTrashServiceImpl.trashDelete4CompetitorAnalysis ", e);
                }
            };
            threadPoolBeanConfig.attrTrashDelete().execute(runnable);
        }
        attrTrashDeleteVO.setCanDel(canDel);
        return attrTrashDeleteVO;
    }

}
